package com.common.util;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ClassLoadUtil {

	
	public static void main(String[] args) {
		List<String> packs=new ArrayList<String>();
		packs.add("comtom.core.common");
		packs.add("org.springframework.aop.scope");
		List<Class<?>> classes=getClassesByPack(packs);
		System.err.println(classes);
	}
	
	/**
	 * 根据包名加载类,只要是当前classPath路径的类都可以过滤
	 * 
	 * @param pack
	 * @return
	 */
	public static List<Class<?>> getClassesByPack(List<String> packs) {
		List<Class<?>> classes = new ArrayList<Class<?>>();
		Set<File> fileList=listPaths();
		for (File file : fileList) {
			dirWalker(packs,file,classes);
		}
		return classes;
	}

	/**
	 * 获取项目的classPath下所有的文件夹和文件
	 * @return 文件列表
	 */
	private static Set<File> listPaths() {
		Set<File> files = new HashSet<File>();
		try {
			Enumeration<URL> urls=Thread.currentThread().getContextClassLoader().getResources("");
			while (urls.hasMoreElements()) {
				URL url = (URL) urls.nextElement();
				files.add(new File(url.getFile()));
			}
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		String jars = System.getProperty("java.class.path");
		if (jars == null) {
			System.err.println("java.class.path is null!");
			return files;
		}
		URL root = Thread.currentThread().getContextClassLoader().getResource("");
		if (root == null) {
			System.err.println("path root is null!");
			return files;
		}
		String path = null;
		try {
			path = URLDecoder.decode(root.getFile(), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return files;
		}
		File dir = new File(path);
		String[] array = (jars).split(";");
		if (array != null) {
			for (String s : array) {
				if (s == null) {
					continue;
				}
				File f = new File(s);
				if (f.exists()) {
					files.add(f);
				} else {// 有些jar就在系统目录下,省略了路径,要加上
					File jar = new File(dir, s);
					if (jar.exists()) {
						files.add(jar);
					}
				}
			}
		}
		return files;
	}

	/**
	 * 遍历文件夹下所有的类
	 * @param packs 包路径
	 * @param file 文件
	 * @param list-保存类列表
	 */
	private static void dirWalker(List<String> packs, File file, Collection<Class<?>> list) {
		if (file.exists()) {
			if (file.isDirectory()) {
				for (File f : file.listFiles()) {
					dirWalker(packs, f, list);
				}
			} else {
				Class<?> c = loadClassByFile(packs, file);
				if (c != null) {
					list.add(c);
				}
			}
		}
	}

	/**
	 * 从文件加载类
	 * @param pkg包路径
	 * @param file文件
	 * @return 类或者null
	 */
	private static Class<?> loadClassByFile(List<String> packs, File file) {
		if (!file.isFile()) {
			return null;
		}
		String name = file.getName();
		if (name.endsWith(".class")) {
			String ap = file.getAbsolutePath();
			String pkg=null;
			for (String string : packs) {
				string = string.replace('.', File.separatorChar);
				if (ap.contains(string)) {
					pkg=string;
					break ;
				}
			}
			if (pkg==null) {
				return null;
			}
			name = ap.substring(ap.indexOf(pkg) + pkg.length());
			if (name.startsWith(File.separator)) {
				name = name.substring(1);
			}
			String path = (pkg + "." + name.substring(0, name.lastIndexOf(".")))
					.replace(File.separatorChar, '.');
			try {
				Class<?> c = Class.forName(path);
				return c;
			} catch (ClassNotFoundException e) {
			}
		}
		return null;
	}
}
